Windows actions#30
Closed
neykov wants to merge 25 commits into
Closed
Conversation
…e instantiated) Three-job workflow (layout-probe → reproduce-windows-attach-dll → workaround-sanity-check) that confirms the ServiceConfigurationError on JDK 8 Temurin when jre\bin is stripped from PATH, and verifies the -Djava.library.path workaround. Triggered via workflow_dispatch. https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
The fix is already present in AttachHelper.java — tryLoadLibrary() finds attach.dll relative to JAVA_HOME and prints "Loaded attach <path>". Update Job 2 assertion to verify the fallback fires and no ServiceConfigurationError appears when jre\bin is stripped from PATH. https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
- Job 2: updated assertion handles both cases — fix fallback fires
("Loaded attach" present) or JVM finds attach.dll via
sun.boot.library.path (no fallback needed, no error)
- Job 3 (new): reverts the loadAttachLibrary() guard in source,
also strips sun.boot.library.path of jre\bin via JVM flag, then
runs the unfixed jar to attempt a conclusive reproduction of the
ServiceConfigurationError
- layout-probe: also prints sun.boot.library.path for diagnosis
- workaround-sanity-check: now runs in parallel with Job 3 (both
depend on verify-fix passing)
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
Replace the unreliable GITHUB_ENV PATH-stripping approach with direct
JVM flags:
-Djava.library.path=.
-Dsun.boot.library.path=.
Setting both to '.' (current dir, no attach.dll) forces
System.loadLibrary("attach") to fail, without touching the process
PATH. This makes every job step self-contained and reliable.
- verify-fix: fix's tryLoadLibrary() finds attach.dll via JAVA_HOME
absolute path; "Loaded attach" must appear
- reproduce-without-fix: remove loadAttachLibrary() guard, same flags,
assert ServiceConfigurationError is produced
- workaround-sanity-check: explicit -Djava.library.path=jre\bin with
-Dsun.boot.library.path=. confirms the manual workaround
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
…h isolation
Previous attempts to override sun.boot.library.path via -D failed because
the JVM overwrites that property at startup after -D arguments are processed.
New approach: inject a reflection snippet into the test code that nulls
ClassLoader.sys_paths and sets sun.boot.library.path="." at runtime.
This forces the next System.loadLibrary("attach") call to re-initialise
both search paths as "." (where attach.dll is absent), faithfully
simulating an environment where jre\bin is absent from all search paths.
- verify-fix: snippet injected into loadAttachLibrary(), fix fallback fires
→ "Loaded attach" must appear
- reproduce-without-fix: snippet in list(), loadAttachLibrary() removed
→ ServiceConfigurationError must appear
- workaround-sanity-check: same as above + -Djava.library.path=jre\bin
→ usr_paths finds attach.dll, no error
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
…snippets The @'...'@ here-string closing delimiter caused a YAML parse error. Encode the Java injection snippets as base64 and decode them in PowerShell at runtime — no special characters to escape in the YAML source. https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
…s manipulation
Replace reflection-based sys_paths clearing with a genuine environment setup:
- Build and supply JAVA_HOME from Temurin JDK 8 (has jre/bin/attach.dll)
- Run the jar using Temurin JRE 8 java.exe (no attach.dll in bin)
- JAVA_HOME=JDK so tools.jar and the fix's fallback path are both reachable
Without fix: WindowsAttachProvider static init calls System.loadLibrary("attach"),
finds nothing on the JRE's sun.boot.library.path, throws ServiceConfigurationError.
With fix: loadAttachLibrary() catches UnsatisfiedLinkError and loads attach.dll
from $JAVA_HOME/jre/bin (JDK), then VirtualMachine.list() succeeds.
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
…-type:jre package-type:jre on Temurin 8 reuses the cached JDK path (Java_Temurin-Hotspot_jdk), so JAVA_HOME_JRE == JAVA_HOME_JDK and attach.dll is present, preventing reproduction. New approach: copy $JAVA_HOME\jre to a temp dir, delete attach.dll from the copy, then run the jar with that copy's java.exe. The copy's sun.boot.library.path (= copy's bin/) has no attach.dll, naturally triggering the ServiceConfigurationError. JAVA_HOME still points to the original JDK for tools.jar and the fix's fallback. https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
…loaded
The JDK ships two copies of attach.dll:
bin\attach.dll — incomplete version used by developer tools; on PATH
jre\bin\attach.dll — full JRE version needed by WindowsAttachProvider
On Windows, java.library.path includes all PATH directories, so
System.loadLibrary("attach") finds bin\attach.dll via PATH even when
sun.boot.library.path (jre copy's bin/) has no attach.dll.
That DLL loads successfully but doesn't export tempPath(), causing
UnsatisfiedLinkError on the native call instead of the expected
ServiceConfigurationError.
Fix: remove bin\attach.dll too, leaving jre\bin\attach.dll intact for the
fix's $JAVA_HOME/jre/bin fallback to load via System.load() (absolute path).
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
Temurin/OpenJDK 8 differs from Oracle JDK 8 in how attach.dll is loaded:
- Oracle: WindowsAttachProvider static init calls System.loadLibrary("attach")
-> class init fails -> ServiceConfigurationError "could not be instantiated"
- Temurin: WindowsAttachProvider has no static library load; tempPath() is a
native method called during listVirtualMachines() before any
WindowsVirtualMachine is created, so without attach.dll it throws:
UnsatisfiedLinkError: WindowsAttachProvider.tempPath()
Both confirm the same root cause: attach.dll unreachable without the fix.
Update the assertion to accept either error pattern.
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
…sert
GitHub Actions' PowerShell runner appends:
if ((Test-Path variable:LASTEXITCODE)) { exit $LASTEXITCODE }
so a non-zero exit from java.exe causes the entire step to fail before
the separate assert step can check the output.
Reset $LASTEXITCODE = 0 after the java invocation; the assert step then
inspects the captured output to determine pass/fail.
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
java.library.path on Windows auto-includes all PATH directories, not just
java.home\bin. Even after removing bin\attach.dll, another copy (or the
jre\bin version) is reachable via PATH, causing System.loadLibrary("attach")
to succeed with the wrong DLL — which doesn't export tempPath().
Fix: pass -Djava.library.path=. to explicitly override java.library.path
with just the current directory (no attach.dll). Combined with the JRE copy
controlling sun.boot.library.path, both sys_paths and usr_paths are clear
of attach.dll, so:
- reproduce job: System.loadLibrary("attach") fails -> UnsatisfiedLinkError
- verify-fix job: loadAttachLibrary() catches it, falls back to
System.load($JAVA_HOME/jre/bin/attach.dll) -> "Loaded attach" -> works
Also simplify setup steps by removing the now-unnecessary JDK bin removal.
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
…anipulation
The actual root cause requires no filesystem manipulation:
- AgentAttach creates URLClassLoader(cp, null) to load tools.jar
- WindowsAttachProvider static init calls System.loadLibrary("attach")
- Called from a non-bootstrap classloader, this searches java.library.path
(= JDK bin, no attach.dll) not sun.boot.library.path (= JRE bin, has it)
- UnsatisfiedLinkError wrapped by SPI loader -> ServiceConfigurationError
Standard Temurin JDK 8 reproduces the issue without any env modification.
https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
Downloads the JRE-only zip (not the JDK) to verify whether attach.dll is present in a standalone JRE installation, and prints its library paths — confirming the real-world scenario that triggers issue #7. https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
Disables the fix so the workflow can verify the error occurs without it. https://claude.ai/code/session_01R7dUoeZm6vv7V1HGKVuseV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I've asked Claude to reproduce the failure in Issue 7. It needed a lot of handholding, but eventually was able to come up with a clean repro case.
ServiceConfigurationError: WindowsAttachProvider could not be instantiated
Error
Root Cause
On Windows with Oracle JDK 8, two separate Java installs coexist:
C:\Program Files\Java\jdk1.8.0_XXX\— hastools.jarandjre\bin\attach.dllC:\Program Files\Java\jre1.8.0_XXX\— has noattach.dllOracle's installer puts the public JRE's
bin\on the system PATH. Users separately setJAVA_HOMEto the JDK for development tools. This creates the failing combination:attach.dll?java.exeon PATHjvm.dllloadedbin\server\sun.boot.library.pathjvm.dlllocation → standalone JREbin\tools.jar(viaJAVA_HOME)lib\tools.jarKey facts
attach.dll— it is only present in the JDK's embedded JRE(
jdk\jre\bin\attach.dll).sun.boot.library.pathis derived purely from the location of the runningjvm.dll, notfrom
JAVA_HOME. It always resolves to thebin\directory two levels abovejvm.dll:System.loadLibrary("attach")searchessun.boot.library.pathfirst, thenjava.library.path(derived from PATH). If neither contains
attach.dll, loading fails.Failure chain
java.exeis the standalone JRE's —com.sun.tools.attach.VirtualMachineis not on theclasspath, so
isAttachApiAvailable()returnsfalse.AgentAttachloadstools.jarfromJAVA_HOMEviaURLClassLoader(cp, null).VirtualMachine.list()triggers the SPI, which attempts to instantiateWindowsAttachProvider.WindowsAttachProvider's static initializer callsSystem.loadLibrary("attach").System.loadLibrarysearchessun.boot.library.path= standalone JREbin\→attach.dllis absent.UnsatisfiedLinkErroris thrown inside the static initializer.Throwableand wraps it:Variant failure
If any
attach.dllis reachable via PATH (e.g. from a different JDK installation), but it isfrom an older version than the
tools.jarbeing used, the static initializer succeeds but alater native method call fails:
tempPath()was added in a later JDK 8 update as a security hardening measure. An olderattach.dllon PATH will load successfully but will not contain this method.Steps to Reproduce